package com.vr.xuecheng.media.util;

import io.minio.*;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.util.List;

/**
 * @author hzh
 * @date 2025/03/11
 * minio工具类
 */
@Log4j2
@RequiredArgsConstructor
@Component
public class MinioUtil {
    private final MinioClient minioClient;


    /**
     * 上传文件
     *
     * @param inputStream  上传的流
     * @param objectName  文件对象名，可以是路径，如：test/test.txt
     * @param bucketName  桶名
     * @param contentType 媒体类型
     * @return boolean 结果
     */
    public boolean uploadFile(InputStream inputStream,long fileSize, String objectName, String bucketName, String contentType) {
        try {
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .stream(inputStream,fileSize, -1)
                            .contentType(contentType)
                            .build()
            );
        } catch (Exception e) {
            log.error("文件上传失败: " + e.getMessage());
            return false;
        }
        return true;
    }


    /**
     * 下载文件
     *
     * @param objectName 文件对象名，可以是路径，如：test/test.txt
     * @param bucketName 桶名
     * @return 文件流
     */
    public InputStream downloadFile(String objectName, String bucketName) {
        try {
            return minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build()
            );
        } catch (Exception e) {
            log.error("文件下载失败:{}", e.getMessage());
        }
        return null;
    }

    /**
     * 删除单个文件
     *
     * @param objectName 文件对象名，可以是路径，如：test/test.txt
     * @param bucketName 桶名
     * @return boolean 结果
     */
    public boolean deleteFile(String objectName, String bucketName) {
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build()
            );
            return true;
        } catch (Exception e) {
            log.error("文件删除失败:{}", e.getMessage());
        }
        return false;
    }

    /**
     * @param bucketName 桶名
     * @param objects 删除文件objectName列表，如：List.of(new DeleteObject("test/test.txt"), new DeleteObject("test/test2.txt"))
     * @return boolean 是否删除成功
     */
    public boolean deleteFiles(String bucketName, Iterable<DeleteObject> objects) {
        try {
            Iterable<Result<DeleteError>> results = minioClient.removeObjects(
                    RemoveObjectsArgs.builder()
                            .bucket(bucketName)
                            .objects(objects)
                            .build()
            );
            results.forEach(result -> {
                try {
                    result.get();
                } catch (Exception e) {
                    log.error("文件批量删除失败:{}", e.getMessage());
                }
            });
            return true;
        } catch (Exception e) {
            log.error("文件批量删除失败:{}", e.getMessage());
        }
        return false;
    }

    /**
     * @param objectName 文件对象名，可以是路径，如：test/test.txt
     * @param bucketName 桶名
     * @return boolean 文件是否存在
     */
    public boolean checkFileExists(String objectName, String bucketName) {
        try {
            StatObjectResponse stat = minioClient.statObject(
                    StatObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build()
            );
            log.debug("文件元数据:{} ", stat.toString());
            return true;
        } catch (Exception e) {
            log.debug("{},文件不存在", e.getMessage());
        }
        return false;
    }

    /**
     * @param objectName 文件对象名，可以是路径，如：test/test.txt
     * @param bucketName 桶名
     * @return {@code StatObjectResponse } 元信息
     * 获取minio文件夹元信息
     */
    public StatObjectResponse getStat(String objectName, String bucketName) {
        try {
            StatObjectResponse stat = minioClient.statObject(
                    StatObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build()
            );
            System.out.println("文件元数据: " + stat);
            return stat;
        } catch (Exception e) {
            log.debug("{},文件不存在", e.getMessage());
        }
        return null;
    }

    /**
     * @param objectName 文件对象名，可以是路径，如：test/test.txt
     * @param bucketName 桶名
     * @param source     源文件列表，也就是块的列表，它会按照这个顺序合并
     * @return boolean 是否合并成功
     * 合并分块
     */
    public boolean mergeChunks(String objectName, String bucketName, List<ComposeSource> source) {
        try {
            minioClient.composeObject(
                    ComposeObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .sources(source)
                            .build()
            );
            log.debug("文件合并成功：{}", objectName);
            return true;
        } catch (Exception e) {
            log.error("{}文件合并失败：{} ", bucketName, e.getMessage());
        }
        return false;
    }
}
